#region File Description
//-----------------------------------------------------------------------------
// RacingGameManager.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using directives
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using System;
using System.Collections.Generic;
using RacingGame.GameLogic;
using RacingGame.GameScreens;
using RacingGame.Graphics;
using RacingGame.Helpers;
using RacingGame.Landscapes;
using RacingGame.Sounds;
using Model = RacingGame.Graphics.Model;
using Texture = RacingGame.Graphics.Texture;
using RacingGame.Properties;
using RacingGame.Shaders;
#endregion

namespace RacingGame
{
	public class RacingGameManager : BaseGame
	{
		#region Variables
		private static Stack<IGameScreen> gameScreens = new Stack<IGameScreen>();
		private static Player player = new Player(new Vector3(0, 0, 0));
		private static Model carModel = null, carSelectionPlate = null;
		private static Texture[] carTextures = null;
		public static int currentCarNumber = 0;
		public static int currentCarColor;// Color carColor = Color.White;
		public static Texture colorSelectionTexture = null;
		private static Material brakeTrackMaterial = null;
		public static List<Color> CarColors = new List<Color>(
			new Color[]
            {
                Color.White,
                Color.Yellow,
                Color.Blue,
                Color.Purple,
                Color.Red,
                Color.Green,
                Color.Teal,
                Color.Gray,
                Color.Chocolate,
                Color.Orange,
                Color.SeaGreen,
            });
		private static Landscape landscape = null;
		public enum Level
		{
			Beginner,
			Advanced,
			Expert,
		}
		public static void LoadLevel(Level setNewLevel)
		{
			landscape.ReloadLevel(setNewLevel);
		}
		#endregion

		#region Properties

		public static bool InMenu
		{
			get
			{
				return gameScreens.Count > 0 &&
					gameScreens.Peek().GetType() != typeof(GameScreen);
			}
		}

		public static bool InGame
		{
			get
			{
				return gameScreens.Count > 0 &&
					gameScreens.Peek().GetType() == typeof(GameScreen);
			}
		}

		public static bool ShowMouseCursor
		{
			get
			{
				// Only if not in Game, not in splash screen!
				return gameScreens.Count > 0 &&
					gameScreens.Peek().GetType() != typeof(GameScreen) &&
					gameScreens.Peek().GetType() != typeof(SplashScreen);
			}
		}

		public static bool InCarSelectionScreen
		{
			get
			{
				return gameScreens.Count > 0 &&
					gameScreens.Peek().GetType() == typeof(CarSelection);
			}
		}

		public static Player Player
		{
			get
			{
				return player;
			}
		}

		public static Model CarModel
		{
			get
			{
				return carModel;
			}
		}

		public static Color CarColor
		{
			get
			{
				return CarColors[currentCarColor % CarColors.Count];
			}
		}

		public static int NumberOfCarColors
		{
			get
			{
				return CarColors.Count;
			}
		}

		public static int NumberOfCarTextureTypes
		{
			get
			{
				return carTextures.Length;
			}
		}

		public static Texture CarTexture(int carNumber)
		{
			return carTextures[carNumber % carTextures.Length];
		}

		public static Material BrakeTrackMaterial
		{
			get
			{
				return brakeTrackMaterial;
			}
		}

		public static Model CarSelectionPlate
		{
			get
			{
				return carSelectionPlate;
			}
		}

		public static Landscape Landscape
		{
			get
			{
				return landscape;
			}
		}
		#endregion

		#region Constructor
		public RacingGameManager()
			: base("RacingGame")
		{
			// Start playing the menu music
			Sound.Play(Sound.Sounds.MenuMusic);

			// Create main menu at our main entry point
			gameScreens.Push(new MainMenu());

			// But start with splash screen, if user clicks or presses Start,
			// we are back in the main menu.
			gameScreens.Push(new SplashScreen());
		}

		public RacingGameManager(string unitTestName)
			: base(unitTestName)
		{
			// Don't add game screens here
		}

		protected override void Initialize()
		{
			base.Initialize();

			// Load models
			carModel = new Model("Car");
			carSelectionPlate = new Model("CarSelectionPlate");

			// Load landscape
			landscape = new Landscape(Level.Beginner);

			// Load textures, first one is grabbed from the imported one through
			// the car.x model, the other two are loaded seperately.
			carTextures = new Texture[3];
			carTextures[0] = new Texture("RacerCar");
			carTextures[1] = new Texture("RacerCar2");
			carTextures[2] = new Texture("RacerCar3");
			colorSelectionTexture = new Texture("ColorSelection");
			brakeTrackMaterial = new Material("track");
		}
		#endregion

		#region Add game screen
		public static void AddGameScreen(IGameScreen gameScreen)
		{
			// Play sound for screen click
			Sound.Play(Sound.Sounds.ScreenClick);

			// Add the game screen
			gameScreens.Push(gameScreen);
		}
		#endregion

		#region Update
		protected override void Update(GameTime gameTime)
		{
			// Update game engine
			base.Update(gameTime);

			// Update player and game logic
			player.Update();
		}
		#endregion

		#region Render
		protected override void Render()
		{
			// No more game screens?
			if (gameScreens.Count == 0)
			{
				// Before quiting, stop music and play crash sound :)
				Sound.PlayCrashSound(true);
				Sound.StopMusic();

				// Then quit
				Exit();
				return;
			}

			// Handle current screen
			if (gameScreens.Peek().Render())
			{
				// If this was the options screen and the resolution has changed,
				// apply the changes
				if (gameScreens.Peek().GetType() == typeof(Options) &&
					(BaseGame.Width != GameSettings.Default.ResolutionWidth ||
					BaseGame.Height != GameSettings.Default.ResolutionHeight ||
					BaseGame.Fullscreen != GameSettings.Default.Fullscreen))
				{
					BaseGame.ApplyResolutionChange();
				}

				// Play sound for screen back
				Sound.Play(Sound.Sounds.ScreenBack);

				gameScreens.Pop();
			}
		}

		protected override void PostUIRender()
		{
			// Enable depth buffer again
			BaseGame.Device.RenderState.DepthBufferEnable = true;

			// Currently in car selection screen?
			if (gameScreens.Count > 0 &&
				gameScreens.Peek().GetType() == typeof(CarSelection))
				((CarSelection)gameScreens.Peek()).PostUIRender();

			// Do menu shader after everything
			if (RacingGameManager.InMenu &&
				PostScreenMenu.Started)
				UI.PostScreenMenuShader.Show();
		}
		#endregion
	}
}
